home *** CD-ROM | disk | FTP | other *** search
/ Reverse Code Engineering RCE CD +sandman 2000 / ReverseCodeEngineeringRceCdsandman2000.iso / RCE / Library / Manuels & Misc / Assembly / AOA.ZIP / CH12 / ITERS.ASM < prev   
Encoding:
Assembly Source File  |  1994-03-14  |  6.0 KB  |  323 lines

  1. ; Iterator example.
  2. ;
  3. ; Roughly corresponds to the example in Ghezzi & Jazayeri's
  4. ; "Programming Language Concepts" text.
  5. ;
  6. ; Randall Hyde
  7. ;
  8. ;
  9. ; This program demonstrates an implementation of:
  10. ;
  11. ;  l := 0;
  12. ;  foreach i in range(1,3) do
  13. ;    foreach j in iter2() do
  14. ;        writeln(i, ',', j, ',', l):
  15. ;
  16. ;
  17. ;  iterator range(start,stop):integer;
  18. ;  begin
  19. ;
  20. ;    while start <= stop do begin
  21. ;
  22. ;        yield start;
  23. ;        start := start+1;
  24. ;    end;
  25. ;  end;
  26. ;
  27. ;  iterator iter2:integer;
  28. ;  var k:integer;
  29. ;  begin
  30. ;
  31. ;    foreach k in iter3 do
  32. ;        yield k;
  33. ;  end;
  34. ;
  35. ;  iterator iter3:integer;
  36. ;  begin
  37. ;
  38. ;    l := l + 1;
  39. ;    yield 1;
  40. ;    l := l + 1;
  41. ;    yield 2;
  42. ;    l := l + 1;
  43. ;    yield 0;
  44. ;  end;
  45. ;
  46. ;
  47. ; This code will print:
  48. ;
  49. ;    1, 1, 1
  50. ;    1, 2, 2
  51. ;    1, 0, 3
  52. ;    2, 1, 4
  53. ;    2, 2, 5
  54. ;    2, 0, 6
  55. ;    3, 1, 7
  56. ;    3, 2, 8
  57. ;    3, 0, 9
  58.  
  59.  
  60.  
  61.  
  62.         .xlist
  63.         include     stdlib.a
  64.         includelib    stdlib.lib
  65.         .list
  66.  
  67.         .286                ;Allow extra adrs modes.
  68.  
  69.  
  70.  
  71. dseg        segment    para stack 'data'
  72.  
  73.  
  74.  
  75. ; Put the stack in the data segment so we can use the small memory model
  76. ; to simplify addressing:
  77.  
  78. stk        byte    1024 dup ('stack')
  79. EndStk        word    0
  80.  
  81. dseg        ends
  82.  
  83.  
  84.  
  85.  
  86.  
  87. cseg        segment    para public 'code'
  88.         assume    cs:cseg, ds:dseg, ss:dseg
  89.  
  90.  
  91.  
  92.  
  93. ; Here's the structure of a resume frame.  Note that this structure isn't
  94. ; actually used in this code.  It is only provided to show you what data
  95. ; is sitting on the stack when Yield builds a resume frame.
  96.  
  97. RsmFrm        struct
  98. ResumeAdrs    word    ?
  99. IteratorLink    word    ?
  100. RsmFrm        ends
  101.  
  102.  
  103.  
  104.  
  105. ; The following macro builds a resume frame and the returns to the caller
  106. ; of an iterator.  It assumes that the iterator and whoever called the
  107. ; iterator have the standard activation record defined above and that we
  108. ; are building the standard resume frame described above.
  109. ;
  110. ; This code wipes out the DX register.  Whoever calls the iterator cannot
  111. ; count on DX being preserved, likewise, the iterator cannot count on DX
  112. ; being preserved across a yield.  Presumably, the iterator returns its
  113. ; value in AX.
  114.  
  115. ActRec        struct
  116. DynamicLink    word    ?        ;Saved BP value.
  117. YieldAdrs    word    ?        ;Return Adrs for proc.
  118. StaticLink    word    ?        ;Static link for proc.
  119. ActRec        ends
  120.  
  121. AR        equ    [bp].ActRec
  122.  
  123. Yield        macro
  124.         mov    dx, AR.YieldAdrs    ;Place to yield back to.
  125.         push    bp            ;Save Iterator link
  126.         mov    bp, AR.DynamicLink    ;Get ptr to caller's A.R.
  127.         call    dx            ;Push resume address and rtn.
  128.         pop    bp            ;Restore ptr to our A. R.
  129.         endm
  130.  
  131.  
  132.  
  133.  
  134.  
  135.  
  136. ; Range(start, stop) - Yields start..stop and then fails.
  137.  
  138. ; The following structure defines the activation record for Range:
  139.  
  140. rngAR        struct
  141. DynamicLink    word    ?        ;Saved BP value.
  142. YieldAdrs    word    ?        ;Return Adrs for proc.
  143. StaticLink    word    ?        ;Static link for proc.
  144. FailAdrs    word    ?        ;Go here when we fail
  145. Stop        word    ?        ;Stop parameter
  146. Start        word    ?        ;Start parameter
  147.  
  148. rngAR        ends
  149.  
  150.  
  151. rAR        equ    [bp].rngAR
  152.  
  153.  
  154. Range        proc
  155.         push    bp
  156.         mov    bp, sp
  157.  
  158. ; While start <= stop, yield start:
  159.  
  160. WhlStartLEStop:    mov    ax, rAR.Start        ;Also puts return value
  161.         cmp    ax, rAR.Stop        ; in AX.
  162.         jnle    RangeFail
  163.  
  164.         yield
  165.  
  166.         inc    rAR.Start
  167.         jmp    WhlStartLEStop
  168.  
  169. RangeFail:      pop    bp            ;Restore Dynamic Link.
  170.         add    sp, 4            ;Skip ret adrs and S.L.
  171.         ret     4            ;Return through fail address.
  172. Range        endp
  173.  
  174.  
  175.  
  176.  
  177. ; Iter2- Just calls iter3() and returns whatever value it generates.
  178. ;
  179. ; Note: Since iter2 and iter3 are at the same lex level, the static link
  180. ; passed to iter3 must be the same as the static link passed to iter2.
  181. ; This is why the "push [bp]" instruction appears below (as opposed to the
  182. ; "push bp" instruction which appears in the calls to Range and iter2).
  183. ; Keep in mind, Range and iter2 are only called from main and bp contains
  184. ; the static link at that point.  This is not true when iter2 calls iter3.
  185.  
  186. iter2        proc
  187.         push    bp
  188.         mov    bp, sp
  189.  
  190.         push    offset i3Fail        ;Failure address.
  191.         push    [bp]            ;Static link is link to main.
  192.         call    iter3
  193.         yield                ;Return value returned by iter3
  194.         ret                ;Resume Iter3.
  195.  
  196. i3Fail:        pop    bp            ;Restore Dynamic Link.
  197.         add    sp, 4            ;Skip return address & S.L.
  198.         ret                 ;Return through fail address.
  199. iter2        endp
  200.  
  201.  
  202.  
  203. ; Iter3() simply yields the values 1, 2, and 0:
  204.  
  205. iter3        proc
  206.         push    bp
  207.         mov    bp, sp
  208.  
  209.         mov    bx, AR.StaticLink    ;Point BX at main's AR.
  210.         inc    word ptr [bx-6]        ;Increment L in main.
  211.         mov    ax, 1
  212.         yield
  213.  
  214.         mov    bx, AR.StaticLink
  215.         inc    word ptr [bx-6]
  216.         mov    ax, 2
  217.         yield
  218.         mov    bx, AR.StaticLink
  219.         inc    word ptr [bx-6]
  220.         mov    ax, 0
  221.         yield
  222.  
  223.         pop    bp            ;Restore Dynamic Link.
  224.         add    sp, 4            ;Skip return address & S.L.
  225.         ret                 ;Return through fail address.
  226. iter3        endp
  227.  
  228.  
  229.  
  230.  
  231.  
  232.  
  233. ; Main's local variables are allocated on the stack in order to justify
  234. ; the use of static links.
  235.  
  236. i        equ    [bp-2]
  237. j        equ    [bp-4]
  238. l        equ    [bp-6]
  239.  
  240.  
  241. Main        proc
  242.         mov    ax, dseg
  243.         mov    ds, ax
  244.         mov    es, ax
  245.         mov    ss, ax
  246.         mov    sp, offset EndStk
  247.  
  248. ; Allocate storage for i, j, and l on the stack:
  249.  
  250.         mov    bp, sp
  251.         sub    sp, 6
  252.  
  253.         meminit
  254.  
  255.         mov    word ptr l, 0        ;Initialize l.
  256.  
  257. ; foreach i in range(1,3) do:
  258.  
  259.         push    1            ;Parameters.
  260.         push    3
  261.         push    offset iFail        ;Failure address.
  262.         push    bp            ;Static link points at our AR.
  263.         call    Range
  264.  
  265. ; Yield from range comes here.  The label is for your benefit.
  266.  
  267. RangeYield:    mov    i, ax            ;Save away loop control value.
  268.  
  269. ; foreach j in iter2 do:
  270.  
  271.         push    offset jfail        ;Failure address.
  272.         push    bp            ;Static link points at our AR.
  273.         call    iter2
  274.  
  275.  
  276. ; Yield from iter2 comes here:
  277.  
  278. iter2Yield:    mov    j, ax
  279.  
  280.         mov    ax, i
  281.         puti
  282.         print
  283.         byte    ", ",0
  284.         mov    ax, j
  285.         puti
  286.         print
  287.         byte    ", ",0
  288.         mov    ax, l
  289.         puti
  290.         putcr
  291.  
  292. ; Restart iter2:
  293.  
  294.         ret                ;Resume iterator.
  295.  
  296.  
  297. ; Restart Range down here:
  298.  
  299. jFail:        ret                ;Resume iterator.
  300.  
  301. ; All Done!
  302.  
  303. iFail:        print
  304.         byte    cr,lf,"All Done!",cr,lf,0
  305.  
  306.  
  307.  
  308.  
  309. Quit:        ExitPgm            ;DOS macro to quit program.
  310. Main        endp
  311.  
  312. cseg            ends
  313.  
  314.  
  315.  
  316. ; zzzzzzseg must be the last segment that gets loaded into memory!
  317. ; This is where the heap begins.
  318.  
  319. zzzzzzseg    segment    para public 'zzzzzz'
  320. LastBytes    db    16 dup (?)
  321. zzzzzzseg    ends
  322.         end    Main
  323.